using System.Collections;
using UnityEngine;
using UnityEngine.Events;

// 直升机主引擎控制脚本
public class HelicopterMainEngineController : MonoBehaviour
{
    [Header("组件引用")]
    [SerializeField] private BladesController topBlade;  // 主旋翼控制器
    [SerializeField] private BladesController tailBlade;   // 尾旋翼控制器
    private Rigidbody _rigidbody;  // 直升机刚体组件

    [Header("输入参数")]
    private bool _isAddingPower;
    private bool _isSubtractingPower;

    [Header("引擎参数")]
    [SerializeField] private float effectiveHeight = 50f; // 有效悬停高度（米）
    [SerializeField] private float _engineLift = 0.0075f;  // 油门增减灵敏度
    private float _mass;                 //质量
    private float _enginePower;          // 当前引擎动力值
    // 引擎动力属性（带旋翼同步控制） 
    public float EnginePower
    {
        get => _enginePower;
        set
        {
            // 主旋翼转速
            topBlade.BladeSpeed = value;
            // 尾旋翼转速
            tailBlade.BladeSpeed = value;
            _enginePower = Mathf.Max(0, value);// 确保不小于0
        }
    }

    [Header("移动参数")]
    [SerializeField] private float forwardForce = 15f;   // 前进施加的力大小
    [SerializeField] private float backwardForce = 15f;  // 后退施加的力大小
    private Vector2 _inputMovement = Vector2.zero;// 存储输入方向的二维向量（初始值为零）

    [Header("地面检测")]
    [SerializeField] private LayerMask groundLayer;       // 用于检测的地面层级
    [SerializeField] private float distance = 5f;        // 射线检测距离
    [SerializeField] private bool isGround = true;      // 是否在地面上
    private RaycastHit _hit;                     // 存储射线检测结果
    private Vector3 _direction;                  //检测方向

    [Header("转向参数")]
    [SerializeField] private float turnForce = 10f;           // 转向力参数（控制直升机转向强度）
    private float _turnSensitivityFactor = 1.5f;   // 转向敏感度系数
    private float _turning = 0f;             // 当前转向值（用于平滑过渡）

    [Header("倾斜参数")]
    [SerializeField] private float maxPitchAngle = 20f;    //前飞时的最大俯仰角度（度）
    [SerializeField] private float maxRollAngle = 30f;       //转向时的最大滚转角度（度）
    private Vector2 _currentTiltAngle = Vector2.zero; // 当前实际倾斜角度

    [Header("悬停参数")]
    [SerializeField] private float hoveringForce = 10f;   //悬停力
    [SerializeField] private float hoverLerpSpeed = 0.003f; //动力调整平滑速度系数

    [Header("倾斜稳定参数")]
    [SerializeField] private float stabilizeForce = 17.5f;//倾斜稳定力
    [SerializeField] private float stabilizeSpeed = 0.003f;//倾斜稳定动力调整平滑速度系数

    [Header("引擎控制")]
    [SerializeField] private float startEnginePower = 8f; // 启动最终到达动力
    [SerializeField] private float engineStartSpeed = 2f; // 过渡时间
    private Coroutine _engineCoroutine; // 引擎协程

    [Header("事件控制")]
    [SerializeField] private UnityEvent OnTakeOff;  // 起飞事件
    [SerializeField] private UnityEvent OnLand;    // 降落事件
    private bool _isTakeOff;  // 是否起飞

    [Header("音效")]
    [SerializeField] private float volumeMaxToEnginePower = 20f; //音效最大对应的引擎动力
    private AudioSource _audioSource;

    [Header("气流粒子")]
    [SerializeField] private ParticleSystem airCurrentParticleSystem;

    void Start()
    {
        _rigidbody = GetComponent<Rigidbody>();
        _audioSource = GetComponent<AudioSource>();
        _mass = _rigidbody.mass;
    }

    void Update()
    {
        ProcessInputs();
        UpdateEnginePower();
        HandleGroundCheck();
        HelicopterTilting();
        HelicopterHovering();
        HelicopterStabilize();
        HandleEngine();
        HandleInvokes();
        HandleSound();
        HandleAirCurrent();
    }

    void FixedUpdate()
    {
        ApplyLiftForce();
        HelicopterMovements();
        HelicopterTurn();
    }

    #region 玩家输入
    /// <summary>
    /// 处理玩家输入控制
    /// </summary>
    void ProcessInputs()
    {
        _isAddingPower = Input.GetKey(KeyCode.Space);
        _isSubtractingPower = Input.GetKey(KeyCode.LeftControl);

        _inputMovement.x = Input.GetAxis("Horizontal");  // 水平输入（左右移动）
        _inputMovement.y = Input.GetAxis("Vertical");    // 垂直输入（前后移动）
    }
    #endregion

    #region 直升机控制
    /// <summary>
    /// 直升机动力
    /// </summary>
    void UpdateEnginePower()
    {
        // 增加动力（Space键）
        if (_isAddingPower) EnginePower += _engineLift;

        // 降低动力（LeftControl键）
        if (_isSubtractingPower) EnginePower -= _engineLift;
    }

    /// <summary>
    /// 计算并应用直升机升力（根据高度自动调节升力效率）
    /// </summary>
    void ApplyLiftForce()
    {
        // 高度衰减系数（0=超过有效高度，1=地面），当前高度越高(heightFactor越小)，升力效率越低
        float heightFactor = 1 - Mathf.Clamp01(_rigidbody.transform.position.y / effectiveHeight);

        // 计算实际升力，使用Lerp在0和EnginePower之间插值，高度越高可用动力越小
        float upForce = Mathf.Lerp(0, EnginePower, heightFactor) * _mass;

        // 在直升机局部坐标系施加升力
        _rigidbody.AddRelativeForce(Vector3.up * upForce);
    }

    /// <summary>
    /// 处理直升机前后移动 
    /// </summary>
    void HelicopterMovements()
    {
        if (isGround) return;

        // 如果输入方向为前（W键或上箭头）
        if (_inputMovement.y > 0)
        {
            // 施加向前的力，大小取决于输入值 (_inputMovement.y)、ForwardForce 和直升机质量
            // Mathf.Max(0f, ...) 确保力不小于0
            _rigidbody.AddRelativeForce(
                Vector3.forward * Mathf.Max(0f, _inputMovement.y * forwardForce * _mass)
            );
        }
        // 如果输入方向为后（S键或下箭头）
        else if (_inputMovement.y < 0)
        {
            // 施加向后的力，取输入绝对值并乘以 backwardForce 和质量
            _rigidbody.AddRelativeForce(
                Vector3.back * Mathf.Max(0f, -_inputMovement.y * backwardForce * _mass)
            );
        }
    }

    /// <summary>
    /// 处理直升机转向
    /// </summary>
    void HelicopterTurn()
    {
        if (isGround) return;

        // 转向力计算（复合运算）
        // 1. 基础转向：movement.x（A/D键输入）
        // 2. 动态调整：TurnForceHelper - 垂直输入绝对值，高速时降低灵敏度，不然容易速度太快导致失控
        // 3. 使用Lerp平滑过渡（Mathf.Max防止负值）
        float turn = turnForce * Mathf.Lerp(
            _inputMovement.x,
            // _inputMovement.x * (_turnSensitivityFactor * Mathf.Abs(_inputMovement.y)),
            _inputMovement.x * (_turnSensitivityFactor - Mathf.Abs(_inputMovement.y)),
            Mathf.Max(0f, _inputMovement.y)
        );

        // 转向平滑过渡（避免突变）
        // Time.fixedDeltaTime保证物理帧率无关
        _turning = Mathf.Lerp(
            _turning,
            turn,
            Time.fixedDeltaTime * turnForce
        );

        // 施加转向扭矩（只在Y轴旋转）
        // 乘以质量保证物理一致性
        _rigidbody.AddRelativeTorque(
            0f,
            _turning * _mass,
            0f
        );
    }
    #endregion

    #region 触发事件
    /// <summary>
    /// 处理事件触发
    /// </summary>
    void HandleInvokes()
    {
        // 当直升机起飞时
        if (!isGround && !_isTakeOff)
        {
            OnTakeOff.Invoke();  // 触发起飞事件
            _isTakeOff = true; // 标记为已起飞
        }

        // 当直升机降落时
        if (isGround && _isTakeOff)
        {
            OnLand.Invoke();     // 触发降落事件
            _isTakeOff = false;  // 标记为已降落
        }
    }
    #endregion

    #region 快速启动关闭引擎
    /// <summary>
    /// 引擎控制
    /// </summary>
    void HandleEngine()
    {
        if (!isGround) return;

        if (Input.GetKeyDown(KeyCode.T)) StartEngine();

        if (Input.GetKeyDown(KeyCode.P)) StopEngine();
    }

    /// <summary>
    /// 启动直升机引擎（平滑增加动力）
    /// </summary>
    void StartEngine()
    {
        if (_engineCoroutine != null)
        {
            StopCoroutine(_engineCoroutine);
        }
        _engineCoroutine = StartCoroutine(LerpEnginePower(EnginePower, startEnginePower, engineStartSpeed));
    }

    /// <summary>
    /// 停止直升机引擎（平滑减少动力）
    /// </summary>
    void StopEngine()
    {
        // 停止当前的引擎协程（如果有的话）
        if (_engineCoroutine != null)
        {
            StopCoroutine(_engineCoroutine);
        }
        _engineCoroutine = StartCoroutine(LerpEnginePower(EnginePower, 0f, engineStartSpeed));
    }

    /// <summary>
    /// 引擎动力插值协程
    /// 实现引擎动力的平滑过渡效果
    /// </summary>
    /// <param name="start">起始动力值</param>
    /// <param name="end">目标动力值</param>
    /// <param name="duration">过渡时间（秒）</param>
    IEnumerator LerpEnginePower(float start, float end, float duration)
    {
        float elapsed = 0f;// 已过去的时间

        // 循环直到达到指定持续时间
        while (elapsed < duration)
        {
            // // Mathf.Lerp在start和end之间根据elapsed / duration比例插值
            EnginePower = Mathf.Lerp(start, end, elapsed / duration);
            // 累加帧时间（使用Time.deltaTime保证帧率无关）
            elapsed += Time.deltaTime;

            yield return null;
        }
        // 确保最终精确达到目标值（避免浮点数精度问题）
        EnginePower = end;
    }
    #endregion

    #region 效果
    /// <summary>
    /// 直升机动力悬停
    /// </summary>
    void HelicopterHovering()
    {
        if (!_isAddingPower && !isGround && _inputMovement.y <= 0.1f)
        {
            EnginePower = Mathf.Lerp(EnginePower, hoveringForce, hoverLerpSpeed);
        }
    }

    /// <summary>
    /// 倾斜稳定直升机发动机功率
    /// </summary>
    void HelicopterStabilize()
    {
        if (!_isAddingPower && !isGround && _inputMovement.y > 0)
        {
            EnginePower = Mathf.Lerp(EnginePower, stabilizeForce, stabilizeSpeed);
        }
    }

    /// <summary>
    /// 直升机机身倾斜效果
    /// </summary>
    void HelicopterTilting()
    {
        if (isGround) return;

        // 俯仰轴（前后倾斜）
        _currentTiltAngle.y = Mathf.Lerp(
            _currentTiltAngle.y,
            _inputMovement.y * maxPitchAngle,
            Time.deltaTime
        );

        // 滚转轴（左右倾斜）
        _currentTiltAngle.x = Mathf.Lerp(
            _currentTiltAngle.x,
            _inputMovement.x * maxRollAngle,
            Time.deltaTime
        );

        // 应用旋转（保持原有偏航角）
        _rigidbody.transform.localRotation = Quaternion.Euler(
            _currentTiltAngle.y,
            _rigidbody.transform.localEulerAngles.y,
            -_currentTiltAngle.x
        );
    }

    /// <summary>
    /// 根据引擎动力调整音量 
    /// </summary>
    void HandleSound(){
        // 将0-volumeMaxToEnginePower的动力值转换为0-1的音量范围
        _audioSource.volume = Mathf.Clamp01(_enginePower / volumeMaxToEnginePower);
    }

    /// <summary>
    /// 气流控制
    /// </summary>
    void HandleAirCurrent()
    {
        if (_enginePower > 0)
        {
            if(!airCurrentParticleSystem.isPlaying) airCurrentParticleSystem.Play();

            // 获取粒子系统的emission模块
            var emission = airCurrentParticleSystem.emission;
            float emissionRate = Mathf.Lerp(1f, 2.5f,  _enginePower / volumeMaxToEnginePower);
            // 设置粒子发射率
            emission.rateOverTime = emissionRate;
        }

        if (_enginePower <= 0 && airCurrentParticleSystem.isPlaying) airCurrentParticleSystem.Stop();
    }
    #endregion

    #region 地面检测
    // 地面检测方法
    void HandleGroundCheck()
    {
        // 将物体的局部坐标系中的"向下"方向转换到世界坐标系。（确保旋转不影响检测方向，比如斜坡着陆时）
        _direction = transform.TransformDirection(Vector3.down);

        // 检测射线是否碰到地面层
        if (Physics.Raycast(transform.position, _direction, out _hit, distance, groundLayer))
        {
            isGround = true;
        }
        // 如果未检测到地面（如悬空状态），则判定为不在地面
        else
        {
            isGround = false;
        }
    }

    //在场景视图显示检测，方便调试
    void OnDrawGizmosSelected()
    {
        Gizmos.color = Color.red;

        //地面检测可视化
        Gizmos.DrawLine(transform.position, transform.position + transform.TransformDirection(Vector3.down) * distance);
    }
    #endregion
}
